package com.suncky.frame.http.config;

import com.suncky.frame.AppConfig;
import com.suncky.frame.http.converter.GsonConverterFactory;
import com.suncky.frame.http.cookie.CookieManger;
import com.suncky.frame.http.interceptor.CacheInterceptor;
import com.suncky.frame.http.interceptor.NetCacheInterceptor;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSocketFactory;

import okhttp3.Cache;
import okhttp3.CookieJar;
import okhttp3.Interceptor;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Converter;

public class OkHttpConfig implements IOkHttpConfig {

    private final Builder builder;

    private OkHttpConfig(Builder builder) {
        this.builder = builder;
    }

    @Override
    public List<Interceptor> getInterceptors() {
        return builder.mInterceptors;
    }

    @Override
    public List<Interceptor> getNetworkInterceptors() {
        return builder.mNetworkInterceptors;
    }

    @Override
    public Cache getCache() {
        return builder.mCache;
    }

    @Override
    public String getBaseUrl() {
        return builder.baseUrl;
    }

    @Override
    public List<Converter.Factory> getConverter() {
        return builder.mConverterFactories;
    }

    @Override
    public SSLSocketFactory getSSlSocketFactory() {
        return builder.sslSocketFactory;
    }

    @Override
    public HostnameVerifier getHostnameVerifier() {
        return builder.hostnameVerifier;
    }

    @Override
    public CookieJar getCookieJar() {
        return builder.cookieJar;
    }

    @Override
    public int getConnectOutTime() {
        return builder.connectOutTime;
    }

    @Override
    public int getReadOutTime() {
        return builder.readOutTime;
    }

    @Override
    public int getWriteOutTime() {
        return builder.writeOutTime;
    }


    public static class Builder {
        private final List<Interceptor> mInterceptors;
        private final List<Interceptor> mNetworkInterceptors;
        private final List<Converter.Factory> mConverterFactories;
        private Cache mCache;
        private String baseUrl;
        private SSLSocketFactory sslSocketFactory;
        private HostnameVerifier hostnameVerifier;
        private CookieJar cookieJar;
        private int connectOutTime;
        private int readOutTime;
        private int writeOutTime;
        private HttpLoggingInterceptor.Logger logger;
        private HttpLoggingInterceptor.Level logLevel;
        private boolean logEnable = true;

        public Builder() {
            mInterceptors = new ArrayList<>();
            mNetworkInterceptors = new ArrayList<>();
            mConverterFactories = new ArrayList<>();
        }

        private void initInterceptors() {
            mInterceptors.add(new CacheInterceptor(60 * 60 * 24));
//            if (mNetworkInterceptors.size() == 0) {
//                mNetworkInterceptors.add(new NetCacheInterceptor(10));
//            }
        }

        private void initLogger() {
            if (logEnable) {
                HttpLoggingInterceptor loggingInterceptor;
                if (logger != null) {
                    loggingInterceptor = new HttpLoggingInterceptor(logger);
                } else {
                    loggingInterceptor = new HttpLoggingInterceptor();
                }
                if (logLevel != null) {
                    loggingInterceptor.level(logLevel);
                } else {
                    loggingInterceptor.level(AppConfig.debug ? HttpLoggingInterceptor.Level.BODY : HttpLoggingInterceptor.Level.NONE);
                }
                mInterceptors.add(loggingInterceptor);
            }
        }

        private void initCache() {
            if (mCache != null) {
                return;
            }
            String parentPath = getCacheParentPath();
            if (parentPath != null) {
                File f = new File(parentPath.concat("/okhttp"));
                if (f.exists() || f.mkdirs()) {
                    mCache = new Cache(f, 5 * 1024 * 1024);
                }
            }
        }

        private void initConverters() {
            if (mConverterFactories.size() == 0) {
                mConverterFactories.add(GsonConverterFactory.create());
            }
        }

        private void initCookie() {
            if (cookieJar == null) {
                cookieJar = new CookieManger(AppConfig.getAppContext());
            }
        }

        public Builder logEnable(boolean logEnable) {
            this.logEnable = logEnable;
            return this;
        }

        public Builder setHttpLogger(HttpLoggingInterceptor.Logger logger, HttpLoggingInterceptor.Level logLevel) {
            this.logger = logger;
            this.logLevel = logLevel;
            return this;
        }

        public Builder addInterceptor(Interceptor interceptor) {
            mInterceptors.add(interceptor);
            return this;
        }

        public Builder addNetworkInterceptor(Interceptor interceptor) {
            mNetworkInterceptors.add(interceptor);
            return this;
        }

        public Builder addConverterFactory(Converter.Factory factory) {
            mConverterFactories.add(factory);
            return this;
        }

        public Builder cache(Cache cache) {
            mCache = cache;
            return this;
        }

        public Builder baseUrl(String url) {
            baseUrl = url;
            return this;
        }

        public Builder sslSocketFactory(SSLSocketFactory sslSocketFactory) {
            this.sslSocketFactory = sslSocketFactory;
            return this;
        }

        public Builder hostnameVerifier(HostnameVerifier hostnameVerifier) {
            this.hostnameVerifier = hostnameVerifier;
            return this;
        }

        public Builder cookieJar(CookieJar cookieJar) {
            this.cookieJar = cookieJar;
            return this;
        }

        public Builder connectOutTime(int connectOutTime) {
            this.connectOutTime = connectOutTime;
            return this;
        }

        public Builder readOutTime(int readOutTime) {
            this.readOutTime = readOutTime;
            return this;
        }

        public Builder writeOutTime(int writeOutTime) {
            this.writeOutTime = writeOutTime;
            return this;
        }

        public OkHttpConfig build() {
            if (baseUrl == null) {
                throw new IllegalStateException("baseUrl can't be null");
            }
            initLogger();
            return new OkHttpConfig(this);
        }

        public OkHttpConfig defaultConfig(String baseUrl) {
            initInterceptors();
            initLogger();
            initConverters();
            initCache();
            initCookie();
            this.baseUrl = baseUrl;
            return new OkHttpConfig(this);
        }

        private String getCacheParentPath() {
            File file = AppConfig.getAppContext().getExternalCacheDir();
            if (file == null || !file.exists()) {
                file = AppConfig.getAppContext().getCacheDir();
            }
            String path = null;
            if (file != null) {
                path = file.getAbsolutePath();
            }
            return path;
        }
    }
}
